//
//  main.m
//  OC07_内存管理
//
//  Created by dllo on 15/12/9.
//  Copyright © 2015年 dllo. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "Person.h"
#import "Student.h"

int main(int argc, const char * argv[]) {
  
#pragma mark - 知识点1 影响内存引用计数的方法
    /** 
     * 增加: alloc retain, copy
     * 减少: release, autorelease
     *
     * 查看引用计数: retainCount 切记: 此方法不要再工程中调用, 因为显示的结果有时是错误的.
     */
#if 0
    {
    Person *per1 = [[Person alloc] init];
    NSLog(@"%ld", [per1 retainCount]);
    
    [per1 retain];
    NSLog(@"%ld", [per1 retainCount]);
    
    [per1 release];
    NSLog(@"%ld", [per1 retainCount]);
    
    [per1 release];
    NSLog(@"%ld", [per1 retainCount]);  /**< 注意: 此时per1的引用计数应该是0, 但是retainCount方法显示的是1, 所以说此方法有时显示不准确 */
    
    
    Person *per2 = [[Person alloc] init];
    [per2 retain];   /** 计数: 2 */
    
    @autoreleasepool {
        
        [per2 autorelease];  /**< 此时不立即 -1, 出了自动释放池之后, 计数才 -1. */
        NSLog(@"%ld", [per2 retainCount]);
        
        
        
    }
    NSLog(@"%ld", [per2 retainCount]);
    }
#endif
    
    
#pragma mark - 知识点2 属性的内存管理
#if 0
    {
        /** 属性的内存管理主要是setter方法的内部实现细节 */
        /** 详见Person类的_name的setter的方法.
         *              _age 的 setter方法
         *
         *
         * 总结: setter方法的具体实现, 不用开发者编写, 属性自动实现. 系统会采用哪种setter实现方式呢? 由定义属性时的语义字段决定(assign, retain, copy)
         */
   
    }
#endif
    
#pragma mark - 知识点3 重写dealloc方法
#if 0
    {
        /** 
         * 为什么要重写dealloc方法.
         * 原因: 对象类型的实例变量(_name), 它的setter方法会引起计数多1, 所以要在适当的时候, 将引用计数-1. 适当的时候就是在整个对象(per1)释放之前. 所以重写dealloc方法
         * 详见Person类
         */
        
    }
#endif
    
    
#pragma mark - 知识点4 属性的getter方法实现
#if 0
    {
        /** 
         * 详见Person的_name 的getter方法.
         *
         * 注意: 当同时编写属性的setter和getter方法时, 系统会提示实例变量不识别. 解决方法: 加上 @synthsize 属性 = _属性名
         */
        
    }
#endif
    
    
#pragma mark - 知识点5 便利构造器的内存问题
#if 0
    {
        /** 详见 Person类. */
        
    }
#endif
    
    
#pragma mark - 知识点6 init方法内部实例变量的写法问题
#if 0
    {
        /** 详见Person类 */
        
    }
#endif
    
#pragma mark - 知识点7 KVC (Key - Value - Coding)
#if 0
    {
       /** 创建一个类: Student, 父类NSObject
        * 只声明实例变量, 不声明属性, 没有setter, getter方法.
        */
        
        Student *stu1 = [[Student alloc] init];
        
        /** 对实例变量进行访问. 使用KVC实现实例变量的访问 */
        [stu1 setValue:@"wangqiang" forKey:@"name"];
        [stu1 setValue:@20 forKey:@"age"];
        [stu1 setValue:@"m" forKey:@"sex"];
        
        /** 使用KVC取值. */
        NSLog(@"name:%@", [stu1 valueForKey:@"name"]);
        NSLog(@"age:%@", [stu1 valueForKey:@"age"]);
        NSLog(@"sex:%@", [stu1 valueForKey:@"sex"]);
        
        
        Student *stu2 = [[Student alloc] init];
        NSDictionary *dic = @{@"name" : @"wangqiang", @"age" : @"30", @"sex" : @"m"};
        
        /** 使用KVC 将字典中的值同时赋给对象的(多个)实例变量 */
        [stu2 setValuesForKeysWithDictionary:dic];
        NSLog(@"name:%@", [stu2 valueForKey:@"name"]);
        
        NSLog(@"sex:%@", [stu2 valueForKey:@"sex"]);
        
    }
#endif
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    return 0;
}
